home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / tools / phwarp.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  12KB  |  630 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    phwarp -
  19.  *        Paul Heckbert and Paul Haeberli team up to warp images
  20.  *    on a Silicon Graphics VGX machine.
  21.  *    
  22.  *                Paul Heckberli - 1990
  23.  */
  24. #include "stdio.h"
  25. #include "math.h"
  26. #include "gl.h"
  27. #include "device.h"
  28.  
  29. #define DEFMESHRES    (50)
  30. #define MAXDIM        (100)
  31. #define RADSCALE     (1.41)
  32. #define WARP_POS    (1)
  33. #define WARP_SIZE    (2)
  34.  
  35. float ease();
  36. #define NKEYS         (8)
  37.  
  38. float flerp();
  39. float wfunc();
  40. float ease();
  41. float sqrt_sum_sq();
  42.  
  43. typedef struct {
  44.     float x, y;
  45. } Point;
  46.  
  47. typedef struct {
  48.     Point orig, warp, wgt; 
  49. } warpPoint;
  50.  
  51. long oldxorg, oldyorg;
  52. long oldxsize, oldysize;
  53. long xsize, ysize;
  54. int lastkey = -1;
  55. int dim, drawgrid;
  56. int warpmode = WARP_POS;
  57. int nsteps = 20;
  58. int fullmode = 0;
  59. float warpradius, aspect;
  60. warpPoint pt[MAXDIM][MAXDIM];
  61. Point key[NKEYS][MAXDIM][MAXDIM];
  62. Point tempkey[MAXDIM][MAXDIM];
  63. FILE *movief;
  64.  
  65. readkeys(name)
  66. char *name;
  67. {
  68.     FILE *inf;
  69.  
  70.     inf = fopen(name,"r");
  71.     if(!inf) {
  72.     fprintf(stderr,"readkeys: can't open input file %s\n",name);
  73.     exit(1);
  74.     }
  75.     fread(&key[0][0][0],1,NKEYS*MAXDIM*MAXDIM*sizeof(Point),inf);
  76.     fclose(inf);
  77. }
  78.  
  79. writekeys(name)
  80. char *name;
  81. {
  82.     FILE *outf;
  83.  
  84.     percentdone(50.0);
  85.     outf = fopen(name,"w");
  86.     if(!outf) {
  87.     fprintf(stderr,"readkeys: can't open input file %s\n",name);
  88.     exit(1);
  89.     }
  90.     fwrite(&key[0][0][0],1,NKEYS*MAXDIM*MAXDIM*sizeof(Point),outf);
  91.     fclose(outf);
  92.     percentdone(100.0);
  93. }
  94.  
  95. float sqrt_sum_sq(x,y)
  96. float x, y;
  97. {
  98.     return fsqrt(x*x+y*y);
  99. }
  100.  
  101. dofunc(n)
  102. int n;
  103. {
  104.     if(myshiftdown())
  105.     loadkey(n);
  106.     else
  107.     lerpkey(n);
  108. }
  109.  
  110. loadkey(n)
  111. int n;
  112. {
  113.     int x, y;
  114.  
  115.     fprintf(stderr,"loading key %d . . .",n+1);
  116.     for(y=0; y<dim; y++) {
  117.     for(x=0; x<dim; x++) {
  118.         key[n][y][x] = pt[y][x].warp;
  119.     }
  120.     }
  121.     fprintf(stderr,"done\n");
  122. }
  123.  
  124. plerp(p0,p1,p,f)
  125. Point *p0, *p1, *p;
  126. float f;
  127. {
  128.     p->x = flerp(p0->x,p1->x,f);
  129.     p->y = flerp(p0->y,p1->y,f);
  130. }
  131.  
  132.  
  133. setnsteps()
  134. {
  135.    float f;
  136.  
  137.    f = 1.0-(getvaluator(MOUSEY)/1024.0);
  138.    nsteps = flerp(3.0,50.0,f*f);
  139.    fprintf(stderr,"\rnsteps is %d  ",nsteps);
  140. }
  141.  
  142. lerpkey(n) 
  143. int n;
  144. {
  145.     int i, x, y;
  146.     float f;
  147.  
  148.     if(n == lastkey)
  149.     return;
  150.     fprintf(stderr,"lerping to  key %d . . .",n+1);
  151.     percentdone(50.0);
  152.     for(y=0; y<dim; y++) {
  153.     for(x=0; x<dim; x++) 
  154.         tempkey[y][x] = pt[y][x].warp;
  155.     }
  156.     for(i=0; i<nsteps; i++) {
  157.     f = i/(nsteps-1.0); 
  158.     f = ease(f);
  159.     for(y=0; y<dim; y++) {
  160.         for(x=0; x<dim; x++) 
  161.         plerp(&tempkey[y][x],&key[n][y][x],&pt[y][x].warp,f);
  162.     }
  163.     drawmesh();
  164.     }
  165.     percentdone(100.0);
  166.     fprintf(stderr,"done\n");
  167. }
  168.  
  169. float myfgetmousex()
  170. {
  171.     return ((float)getvaluator(MOUSEX)-oldxorg)/oldxsize;
  172. }
  173.  
  174. float myfgetmousey()
  175. {
  176.     return ((float)getvaluator(MOUSEY)-oldyorg)/oldysize;
  177. }
  178.  
  179. main(argc,argv)
  180. int argc;
  181. char **argv;
  182. {
  183.     int menu;
  184.     short val, i;
  185.     float initx, inity;
  186.     float newx, newy;
  187.     float dx, dy;
  188.     float initrad, newrad, dr;
  189.  
  190.     if(argc<2) {
  191.     fprintf(stderr,"usage: warp inimage.rgb [file.key]\n");
  192.     exit(1);
  193.     }
  194.     drawgrid = 0;
  195.     warpradius = 0.2;
  196.     dim = DEFMESHRES;
  197.  
  198.     initwarp();
  199.     if(argc == 3)
  200.     readkeys(argv[2]);
  201.     else {
  202.     for(i=0; i<NKEYS; i++)
  203.         loadkey(i);
  204.     }
  205.     sizeofimage(argv[1],&xsize, &ysize);
  206.     keepaspect(xsize,ysize);
  207.     aspect = xsize/(float)ysize;
  208.     if(getgdesc(GD_TEXTURE) == 0) {
  209.     fprintf(stderr,"sorry - phwarp needs texture mapping\n");
  210.     exit(1);
  211.     }
  212.     winopen("phwarp");
  213.     makeframe();
  214.     doublebuffer();
  215.     RGBmode();
  216.     gconfig();
  217.     cpack(0x00000000);
  218.     clear();
  219.     swapbuffers();
  220.     textureread(argv[1],1);
  221.     settexture(0);
  222.     qmouse();
  223.     qdevice(ESCKEY);
  224.     qdevice(UPARROWKEY);
  225.     qdevice(DOWNARROWKEY);
  226.     qdevice(F1KEY);
  227.     qdevice(F2KEY);
  228.     qdevice(F3KEY);
  229.     qdevice(F4KEY);
  230.     qdevice(F5KEY);
  231.     qdevice(F6KEY);
  232.     qdevice(F7KEY);
  233.     qdevice(F8KEY);
  234.     qdevice(F12KEY);
  235.     drawmesh();
  236.     menu = defpup("phwarp %t|restore image|pos warp|size warp|toggle mesh|save image|store out.key|save movie|help|quit");
  237.     while(1) {
  238.     switch(qread(&val)) {
  239.         case REDRAW:
  240.             makeframe();
  241.         drawmesh();
  242.         break;
  243.         case ESCKEY:
  244.         exit(0);
  245.         break;
  246.         case F1KEY:
  247.         if(val) 
  248.             dofunc(0);
  249.         break;
  250.         case F2KEY:
  251.         if(val) 
  252.             dofunc(1);
  253.         break;
  254.         case F3KEY:
  255.         if(val) 
  256.             dofunc(2);
  257.         break;
  258.         case F4KEY:
  259.         if(val) 
  260.             dofunc(3);
  261.         break;
  262.         case F5KEY:
  263.         if(val) 
  264.             dofunc(4);
  265.         break;
  266.         case F6KEY:
  267.         if(val) 
  268.             dofunc(5);
  269.         break;
  270.         case F7KEY:
  271.         if(val) 
  272.             dofunc(6);
  273.         break;
  274.         case F8KEY:
  275.         if(val) 
  276.             dofunc(7);
  277.         break;
  278.         case F12KEY:
  279.         if(val) 
  280.             toggleperformance();
  281.         break;
  282.         case LEFTMOUSE:
  283.         if(val) {
  284.             switch(warpmode) {
  285.             case WARP_POS:
  286.                 initx = myfgetmousex();
  287.                 inity = myfgetmousey();
  288.                 posweightmesh(initx,inity,warpradius);
  289.                 while(getbutton(LEFTMOUSE)) {
  290.                 newx = myfgetmousex();
  291.                 newy = myfgetmousey();
  292.                 dx = newx-initx;
  293.                 dy = newy-inity;
  294.                 posmovemesh(dx,dy);
  295.                 drawmesh();
  296.                 initx = newx;
  297.                 inity = newy;
  298.                 }
  299.                 break;
  300.             case WARP_SIZE:
  301.                 initx = myfgetmousex();
  302.                 inity = myfgetmousey();
  303.                 initrad = 0;
  304.                 sizeweightmesh(initx,inity,warpradius);
  305.                 while(getbutton(LEFTMOUSE)) {
  306.                 newx = myfgetmousex();
  307.                 newy = myfgetmousey();
  308.                 dx = aspect*(newx-initx);
  309.                 dy = newy-inity;
  310.                 newrad = sqrt_sum_sq(dx,dy);
  311.                 dr = newrad-initrad;
  312.                 if(newy>inity)
  313.                     sizemovemesh(dr);
  314.                 else
  315.                     sizemovemesh(-dr);
  316.                 drawmesh();
  317.                 initrad = newrad;
  318.                 }
  319.                 break;
  320.             }
  321.         }
  322.         break;
  323.         case MIDDLEMOUSE:
  324.         if(val) {
  325.             while(getbutton(MIDDLEMOUSE))
  326.             setnsteps();
  327.             fprintf(stderr,"nsteps is %d\n",nsteps);
  328.         }
  329.         break;
  330.         case UPARROWKEY:
  331.         if(val) {
  332.             warpradius *= RADSCALE;
  333.             fprintf(stderr,"warp rad is %f\n",warpradius);
  334.         }
  335.         break;
  336.         case DOWNARROWKEY:
  337.         if(val) {
  338.             warpradius /= RADSCALE;
  339.             fprintf(stderr,"warp rad is %f\n",warpradius);
  340.         }
  341.         break;
  342.         case MENUBUTTON:
  343.         if(val) {
  344.             switch(dopup(menu)) {
  345.             case 1:
  346.                 initwarp();
  347.                 drawmesh();
  348.                 break;
  349.             case 2:
  350.                 warpmode = WARP_POS;
  351.                 break;
  352.             case 3:
  353.                 warpmode = WARP_SIZE;
  354.                 break;
  355.             case 4:
  356.                 drawgrid = 1-drawgrid;
  357.                 drawmesh();
  358.                 break;
  359.             case 5:
  360.                 fprintf(stderr,"saving window to temp.rgb....");
  361.                 savewindow("temp.rgb");
  362.                 fprintf(stderr,"done\n");
  363.                 break;
  364.             case 6:
  365.                 writekeys("out.key");
  366.                 break;
  367.             case 7:
  368.                 savemovie("warp.mov");
  369.                 break;
  370.             case 8:
  371.                 printhelp();
  372.                 break;
  373.             case 9:
  374.                 exit(0);
  375.                 break;
  376.             }
  377.         }
  378.  
  379.     }
  380.     }
  381. }
  382.  
  383.  
  384. makeframe()
  385. {
  386.     float x1, y1, x2, y2;
  387.  
  388.     reshapeviewport();
  389.     if(fullmode) {
  390.     x1 = -(float)oldxorg/oldxsize;
  391.     x2 = (float)(XMAXSCREEN-oldxorg)/oldxsize;
  392.     y1 = -(float)oldyorg/oldysize;
  393.     y2 = (float)(YMAXSCREEN-oldyorg)/oldysize;
  394.     ortho2(x1,x2,y1,y2);
  395.     } else {
  396.     getsize(&oldxsize,&oldysize);
  397.     getorigin(&oldxorg,&oldyorg);
  398.     ortho2(0.0,1.0,0.0,1.0);
  399.     }
  400. }
  401.  
  402. toggleperformance()
  403. {
  404.     fullmode = 1-fullmode;
  405.     if(fullmode) {
  406.     getsize(&oldxsize,&oldysize);
  407.     getorigin(&oldxorg,&oldyorg);
  408.     keepaspect(5,4);
  409.     winconstraints();
  410.     winposition(0,XMAXSCREEN,0,YMAXSCREEN);
  411.     } else {
  412.     keepaspect(xsize,ysize);
  413.     winconstraints();
  414.     winposition(oldxorg,oldxorg+oldxsize-1,oldyorg,oldyorg+oldysize-1);
  415.     }
  416. }
  417.  
  418. drawmesh()
  419. {
  420.     int x, y;
  421.  
  422.     cpack(0x00000000);
  423.     clear();
  424.     if(drawgrid) {
  425.     cpack(0xffe0e0e0);
  426.     for(y=0; y<(dim-1); y++) {
  427.         for(x=0; x<(dim-1); x++) {
  428.         bgnclosedline();
  429.         v2f((float *)&pt[y+0][x+0].warp);
  430.         v2f((float *)&pt[y+0][x+1].warp);
  431.         v2f((float *)&pt[y+1][x+1].warp);
  432.         v2f((float *)&pt[y+1][x+0].warp);
  433.         endclosedline();
  434.         }
  435.         }
  436.    } else {
  437.     settexture(1);
  438.         mytmcolor(0x00ffffff);
  439.     for(y=0; y<(dim-1); y++) {
  440.         for(x=0; x<(dim-1); x++) {
  441.         bgnpolygon();
  442.         t2f((float *)&pt[y+0][x+0].orig);
  443.         v2f((float *)&pt[y+0][x+0].warp);
  444.         t2f((float *)&pt[y+0][x+1].orig);
  445.         v2f((float *)&pt[y+0][x+1].warp);
  446.         t2f((float *)&pt[y+1][x+1].orig);
  447.         v2f((float *)&pt[y+1][x+1].warp);
  448.         t2f((float *)&pt[y+1][x+0].orig);
  449.         v2f((float *)&pt[y+1][x+0].warp);
  450.         endpolygon();
  451.         }
  452.     }
  453.     settexture(0);
  454.     }
  455.     if(movief) 
  456.     addscreenframe();
  457.     swapbuffers();
  458. }
  459.  
  460. initwarp()
  461. {
  462.     int i, j;
  463.  
  464.     for (i=0; i<dim; i++)
  465.     for (j=0; j<dim; j++) {
  466.         pt[i][j].orig.x = pt[i][j].warp.x = (float)j/(dim-1);
  467.         pt[i][j].orig.y = pt[i][j].warp.y = (float)i/(dim-1);
  468.     }
  469. }
  470.  
  471. float wfunc(dist,rad)
  472. float dist, rad;
  473. {
  474.     float ret;
  475.  
  476.     ret =  1.0-dist/rad;
  477.     if(ret<0.0)
  478.     return 0.0;
  479.     return ease(ret);
  480. }
  481.  
  482. posweightmesh(x, y, r)
  483. float x, y, r;
  484. {
  485.     int i, j;
  486.     warpPoint *p;
  487.     float dist;
  488.     float dx, dy;
  489.  
  490.     for (i=0; i<dim; i++) {
  491.     for (j=0; j<dim; j++) {
  492.         p = &pt[i][j];
  493.         dx = p->warp.x-x;
  494.         dy = p->warp.y-y;
  495.         dist = sqrt_sum_sq(aspect*dx,dy);
  496.         p->wgt.x = p->wgt.y = wfunc(dist,r);
  497.     }
  498.     }
  499. }
  500.  
  501. posmovemesh(dx, dy)
  502. float dx, dy;
  503. {
  504.     int i, j;
  505.     warpPoint *p;
  506.  
  507.     for (i=0; i<dim; i++) {
  508.     for (j=0; j<dim; j++) {
  509.         p = &pt[i][j];
  510.         p->warp.x += p->wgt.x*dx;
  511.         p->warp.y += p->wgt.y*dy;
  512.     }
  513.     }
  514. }
  515.  
  516. sizeweightmesh(x, y, r)
  517. float x, y, r;
  518. {
  519.     int i, j;
  520.     warpPoint *p;
  521.     float dist;
  522.     float dx, dy;
  523.  
  524.     for (i=0; i<dim; i++) {
  525.     for (j=0; j<dim; j++) {
  526.         p = &pt[i][j];
  527.         dx = p->warp.x-x;
  528.         dy = p->warp.y-y;
  529.         dist = sqrt_sum_sq(aspect*dx,dy);
  530.         p->wgt.x = dx * wfunc(dist,r);
  531.         p->wgt.y = dy * wfunc(dist,r);
  532.     }
  533.     }
  534. }
  535.  
  536. sizemovemesh(dr)
  537. float dr;
  538. {
  539.     int i, j;
  540.     warpPoint *p;
  541.  
  542.     dr = 5.0*dr;
  543.     for (i=0; i<dim; i++) {
  544.     for (j=0; j<dim; j++) {
  545.         p = &pt[i][j];
  546.         p->warp.x += p->wgt.x*dr;
  547.         p->warp.y += p->wgt.y*dr;
  548.     }
  549.     }
  550. }
  551.  
  552. /* 
  553.  *    library support follows
  554.  *
  555.  *
  556.  */
  557. myqmouse()
  558. {
  559.      qdevice(LEFTMOUSE);
  560.      qdevice(MIDDLEMOUSE);
  561.      qdevice(RIGHTMOUSE);
  562. }
  563.  
  564. mytmcolor(c)
  565. long c;
  566. {
  567.     cpack(c);
  568. }
  569.  
  570. printhelp()
  571. {
  572.     printf("\n\nphwarp - Paul Heckbert and Paul Haeberli team up to warp images\n\n");
  573.  
  574.     printf("This program allows you to inteactively warp an image on a SGI\n");
  575.     printf("VGX machine. There two warp modes supported by this program:\n\n");
  576.     printf("    1. Pos Warp - this warps the position of part of the image\n");
  577.     printf("    2. Size Warp - this warps the size of part of the image\n\n");
  578.     printf("The current warp mode may be selected by interacting with\n");
  579.     printf("the menu.  Depressing the left mouse button choses an orgin for\n"); 
  580.     printf("warping.  Then, as the mouse is moved, a control grid is altered\n");
  581.     printf("using the current warp diameter.  The current warp diameter can\n");
  582.     printf("be made larger, or smaller by pressing the up and down arrow\n");
  583.     printf("keys.  Every two arrow clicks will double or half the size of\n");
  584.     printf("the affected area.  Initially only the control mesh is displayed.\n");
  585.     printf("By selecting 'toggle mesh' the program can be made to display the\n");
  586.     printf("texture mapped image in real time.\n\n");
  587.     printf("Have fun!!\n");
  588. }
  589.  
  590. myshiftdown()
  591. {
  592.    if(getbutton(LEFTSHIFTKEY) || getbutton(RIGHTSHIFTKEY))
  593.        return 1;
  594.    else
  595.        return 0;
  596. }
  597.  
  598. savemovie(name)
  599. char *name;
  600. {
  601.     long xsize, ysize;
  602.  
  603.     lerpkey(0);
  604.     movief = fopen(name,"w");
  605.     if(!movief) {
  606.         fprintf(stderr,"vidtomov: can't open output file\n",name);
  607.         exit(1);
  608.     }
  609.     getsize(&xsize,&ysize);
  610.     createmovie(movief,xsize,ysize,4.0);
  611.     lerpkey(1);
  612.     lerpkey(2);
  613.     lerpkey(3);
  614.     lerpkey(0);
  615.     ringbell();
  616.     fclose(movief);
  617.     movief = 0;
  618. }
  619.  
  620. addscreenframe()
  621. {
  622.     long xsize, ysize;
  623.     unsigned long *lptr;
  624.  
  625.     getsize(&xsize,&ysize);
  626.     lptr = (unsigned long *)malloc(xsize*ysize*sizeof(long));
  627.     lrectread(0,0,xsize-1,ysize-1,lptr);
  628.     addframe(movief,lptr,xsize,ysize);
  629. }
  630.